package cn.fboost.mtos.interceptor;

import cn.fboost.mtos.annotation.IgnoreTokenCheck;
import cn.fboost.mtos.dto.Response;
import cn.fboost.mtos.dto.internal.Session;
import cn.fboost.mtos.entity.Admin;
import cn.fboost.mtos.entity.User;
import cn.fboost.mtos.mapper.AdminMapper;
import cn.fboost.mtos.mapper.UserMapper;
import cn.fboost.mtos.util.InterceptorResponseUtil;
import cn.fboost.mtos.util.SessionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Nonnull;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 登录拦截器
 */
@Slf4j
@Component
public class SessionInterceptor implements HandlerInterceptor {
    private final UserMapper userMapper;
    private final AdminMapper adminMapper;
    private final SessionUtil sessionUtil;


    public SessionInterceptor(UserMapper userMapper, AdminMapper adminMapper, SessionUtil sessionUtil) {
        this.userMapper = userMapper;
        this.adminMapper = adminMapper;
        this.sessionUtil = sessionUtil;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, @Nonnull HttpServletResponse response, @Nonnull Object handler) {
        String token = request.getHeader("access-token");
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod))
            return true;

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        Class<?> clazz = handlerMethod.getBean().getClass();
        // 检查是否需要进行session拦截检测
        if (!method.isAnnotationPresent(IgnoreTokenCheck.class) &&
                !clazz.isAnnotationPresent(IgnoreTokenCheck.class)) {
            Session session = sessionUtil.getSession(token);
            if (session == null) {
                InterceptorResponseUtil.response(response, Response.builder()
                        .ret(Response.Ret.TOKEN_INVALID)
                        .msg("会话已过期，请重新登录")
                        .build()
                );

                return false;
            }

            if (session.getRole() == Session.Role.USER) {
                User user = userMapper.find(session.getId());
                if (user == null) {
                    // 用户不存在，删除session
                    sessionUtil.deleteSession(token);
                    InterceptorResponseUtil.response(response, Response.builder()
                            .ret(Response.Ret.TOKEN_INVALID)
                            .msg("会话不存在，请重新登录")
                            .build()
                    );

                    return false;
                }

                session.setUser(user);
            } else if (session.getRole() == Session.Role.ADMIN) {
                Admin admin = adminMapper.findById(session.getId());
                if (admin == null) {
                    // 管理员不存在，删除session
                    sessionUtil.deleteSession(token);
                    InterceptorResponseUtil.response(response, Response.builder()
                            .ret(Response.Ret.TOKEN_INVALID)
                            .msg("会话不存在，请重新登录")
                            .build()
                    );

                    return false;
                }
            }

            // 更新session
            sessionUtil.refreshSession(token, session);

            // 将用户信息放入request中
            request.setAttribute("current_session", session);
        }

        return true;
    }
}
